using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace OpenComposite.Base.Designer
{
	public class TextBox : DesignerControl
	{
		#region Initialization
		public TextBox()
		{
			init();
		}
		private void init()
		{
			this.BeginUpdate();
			this.Cursor = Cursors.IBeam;
			this.ContextMenuStrip.Items.Clear();

			//this.Name = "textBox" + GetCount(typeof(TextBox));
			this.Text = this.Name;

			this.BackColor = Color.Transparent;

			this.MinimumSize = new Size(10, 10);

			_bAutoSize = true;
			_isEditing = false;
			_borderVisibilityStyle = BorderVisibilityStyle.MouseOverAndFocus;

			_txtEdit = new System.Windows.Forms.TextBox();
			_txtEdit.Visible = false;
			_txtEdit.KeyDown += new KeyEventHandler(_txtEdit_KeyDown);

			_penBorder = new Pen(Color.Gray);
			_penBorder.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

			_format = new StringFormat();
			_format.Trimming = StringTrimming.EllipsisCharacter;
			this.EndUpdate();
		}

		#endregion

		#region Public Members

		#region Properties

		public BorderVisibilityStyle BorderVisibilityStyle
		{
			get { return _borderVisibilityStyle; }
			set {
				if ( _borderVisibilityStyle != value ) {
					_borderVisibilityStyle = value;
					Repaint();
				}
			}
		}

		public HorizontalAlignment TextAlign
		{
			get { return _txtEdit.TextAlign; }
			set
			{
				_txtEdit.TextAlign = value;
				switch ( value ) {
					case HorizontalAlignment.Center:
						_format.Alignment = StringAlignment.Center;
						break;
					case HorizontalAlignment.Left:
						_format.Alignment = StringAlignment.Near;
						break;
					case HorizontalAlignment.Right:
						_format.Alignment = StringAlignment.Far;
						break;
				}
			}
		}

		public bool AutoSize
		{
			get { return _bAutoSize; }
			set { _bAutoSize = value; }
		}
		public bool ReadOnly
		{
			get { 
				return _txtEdit.ReadOnly;
			}
			set {
				_txtEdit.ReadOnly = value;
				this.Cursor = ( _txtEdit.ReadOnly ? Cursors.Default : Cursors.IBeam );
			}
		}
		public int MaxLength
		{
			get { return _txtEdit.MaxLength; }
			set { _txtEdit.MaxLength = value; }
		}

		public System.Windows.Forms.TextBox SystemTextBox
		{
			get { return _txtEdit; }
		}
		public bool IsEditing
		{
			get { return _isEditing; }
			protected set
			{
				if ( _isEditing != value ) {
					_isEditing = value;
					OnIsEditingChanged();
				}
			}
		}

		#endregion

		#region Events
		public event EventHandler IsEditingChanged = null;
		//public event
		#endregion

		#region Methods
		public void Edit()
		{
			showTextBox();
		}
		#endregion

		#region Overrides

		public override bool CanFocused
		{
			get
			{
				return true;
			}
		}
		public override bool CanSelect
		{
			get
			{
				return false;
			}
		}

		public override void Dispose()
		{
			dispose(_penBorder);
			dispose(_txtEdit);

			base.Dispose();
		}
		public override void Paint(PaintEventArgs pe)
		{
			Rectangle bounds = GetPaintBounds();
			pe.Graphics.FillRectangle(this.BackBrush, bounds);

			if ( BorderVisibilityStyle == BorderVisibilityStyle.Always ||
				 ( Status.MouseOverCtrl == this && ( BorderVisibilityStyle == BorderVisibilityStyle.MouseOver || BorderVisibilityStyle == BorderVisibilityStyle.MouseOverAndFocus ) ) ||
				 ( Status.FocusedContol == this && ( BorderVisibilityStyle == BorderVisibilityStyle.Focus || BorderVisibilityStyle == BorderVisibilityStyle.MouseOverAndFocus ) )
			) {
				SmoothingMode sm = pe.Graphics.SmoothingMode;
				pe.Graphics.SmoothingMode = SmoothingMode.None;
				pe.Graphics.DrawRectangle(_penBorder, bounds);
				pe.Graphics.SmoothingMode = sm;
			}
			pe.Graphics.DrawString(this.Text, this.Font, this.ForeBrush, bounds, _format);
		}

		public override string ToString()
		{
			return this.Text;
		}

		#endregion

		#endregion

		#region Protected Members

		#region Methods
		protected virtual void OnIsEditingChanged()
		{
			EventHandler tmp = this.IsEditingChanged;
			if ( tmp != null ) {
				tmp(this, EventArgs.Empty);
			}
		}
		#endregion

		#region Overrides
		protected override void OnTextChanged(EventArgs e)
		{
			this.BeginUpdate();
			if ( this.AutoSize && this.DesignerViewControl != null ) {
				Rectangle rparent = Rectangle.Empty;
				if ( this.Parent != null )
					rparent = this.Parent.ClientRectangle;
				using ( Graphics g = this.DesignerViewControl.CreateGraphics() ) {
					SizeF s = g.MeasureString(this.Text, this.Font);
					if ( rparent != Rectangle.Empty && s.Width > rparent.Width ) {
						s = g.MeasureString(this.Text, this.Font, rparent.Width);
						if ( s.Height > rparent.Height )
							s.Height = rparent.Height;
					}
					if ( this.Width != (int)s.Width ) this.Width = (int)Math.Ceiling(s.Width);
					if ( this.Height != (int)s.Height ) this.Height = (int)Math.Ceiling(s.Height);
				}
			}
			this.EndUpdate();
			base.OnTextChanged(e);
		}
		protected override void OnMouseEnter(EventArgs e)
		{
			base.OnMouseEnter(e);
			this.Refresh();
		}
		protected override void OnMouseLeave(EventArgs e)
		{
			base.OnMouseLeave(e);
			this.Refresh();
		}

		protected override void OnDesignerViewChanged(EventArgs e)
		{
			base.OnDesignerViewChanged(e);
			if ( this.DesignerViewControl != null ) {
				this.DesignerViewControl.ViewControls.Add(_txtEdit);
			}
		}
		protected override void OnMouseClick(MouseEventArgs e)
		{
			base.OnMouseClick(e);
			if ( !this.ReadOnly )
				showTextBox();
		}
		
		#endregion

		#endregion

		#region Private Members

		#region Variables

		private bool _bAutoSize;
		private bool _isEditing;

		private BorderVisibilityStyle _borderVisibilityStyle;

		private Pen _penBorder;
		private StringFormat _format;
		private System.Windows.Forms.TextBox _txtEdit;

		#endregion

		#region Methods

		private void showTextBox()
		{
			Rectangle bounds = this.Bounds;
			if ( this.Parent != null )
				bounds = this.Parent.RectangleToDesignerView(bounds);

			if ( this.DesignerViewControl != null )
				this.DesignerViewControl.MouseDown += new MouseEventHandler(DesignerViewControl_MouseDown);

			_txtEdit.Location = bounds.Location;
			_txtEdit.Width = bounds.Width + 20;
			_txtEdit.Text = this.Text;
			_txtEdit.Visible = true;
			_txtEdit.Focus();
			_txtEdit.SelectAll();
			this.IsEditing = true;
			this.Status.ActiveTextBox = this;
		}
		private void hideTextBox(bool bCancel)
		{
			if ( this.DesignerViewControl != null )
				this.DesignerViewControl.MouseDown -= new MouseEventHandler(DesignerViewControl_MouseDown);

			_txtEdit.Visible = false;
			if ( !bCancel )
				this.Text = _txtEdit.Text;

			this.IsEditing = false;

			this.Status.ActiveTextBox = null;
		}
		
		#endregion

		#region Event Handlers

		private void _txtEdit_KeyDown(object sender, KeyEventArgs e)
		{
			if ( e.KeyCode == Keys.Escape )
				hideTextBox(true);
			else if ( e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return )
				hideTextBox(false);
		}

		private void DesignerViewControl_MouseDown(object sender, MouseEventArgs e)
		{
			hideTextBox(false);
		}

		#endregion

		#endregion
	}
}
